
use axum::Json;
use thiserror::Error as ThisErrorTrait;  //thiserror 可以 让Struct或 Enum 类型，通过 derive(Error) 成为一个Error
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use serde_json::json;
use sqlx::Error as SqlxError;
use jsonwebtoken::errors::Error as JwtError;

//自定义错误
#[derive(ThisErrorTrait, Debug)]
pub enum CustomError {
    #[error("未授权")]
    UnAuth, //未授权

    #[error("JwtError: {0}")]
    JwtError(#[from] JwtError),//可以将  JwtError(三方Err) 转化成 CustomError::JwtError

    #[error("SqlError: {0}")]
    SqlError(#[from] SqlxError), //可以将  SqlxError(三方Err) 转化成 CustomError::SqlxError

    #[error("ApiError: {0}")]
    ApiError(#[from] ApiError), //可以将 ApiError(三方Err) 转化成  CustomError::ApiError

    #[error("TipError: {0}")]
    TipError(String),   //提示错误
}

// 定义 CustomError::ApiError
#[derive(ThisErrorTrait, Debug, PartialEq, Clone, Copy)]

pub enum ApiError {

    #[error("解析http Header失败")]
    FailedToResolveTypedHeader = 1001,

    #[error("token过期,请重新登陆")]
    TokenExpiration = 1003,

    #[error("用户名已存在")]
    UserNameExists = 1004, //用户注册，用户名已存在

    #[error("不存在该用户")]
    UserUnExists = 1005,  //用户登录，不存在用户名

    #[error("登录密码错误")] //用户登录， 登录密码错误
    UserPwdErr = 1006,

    #[error("无效的原始token")] //用户刷新token， 原始token不存在
    InvalidOriginToken = 1007,
}

// api 返回数据类型
// #[derive(Serialize, Deserialize, Debug, Clone)]
// pub struct AppResponse<T> {
//     pub code: i32,
//     pub data: Option<T>,
//     pub msg: Option<String>,
// }
// impl<T> AppResponse<T> {
//     pub fn new(data_:T) -> Self {
//         AppResponse {
//             code: 200,
//             data: Some(data_),
//             msg: None
//         }
//     }
// }

// 定义 CustomResult
// CustomResult中的 T 和  CustomError 都必须实现了 IntoResponse， CustomResult 才能 成为'Response'
pub type CustomResult<T> = Result<T, CustomError>;

// 为  CustomError 实现  IntoResponse  当请求失败时会以 {code: msg:} 传递数据
// CustomError 作为响应 其格式是 
// (StatusCode::BAD_REQUEST, {code:10086, msg:"错误信息"})
//
impl IntoResponse for CustomError {
    fn into_response(self) -> Response {
        let e_code: u32;  //错误码
        let e_msg: String; //错误描述
        match self {
            CustomError::UnAuth => {
                e_code = 401;
                e_msg = "未授权".to_string()
            },

            //提示错误
            CustomError::TipError(e) => {
                e_code = 500;
                e_msg = e.to_string()
            },

            //jwt错误
            CustomError::JwtError(e) => {
                e_code = 401;
                e_msg = e.to_string()
            },

            //数据库错误
            CustomError::SqlError(e) => {
                e_code = 500;
                e_msg = e.to_string()
            },
            //api错误
            CustomError::ApiError(e) => {
                e_code = e as u32;
                e_msg = e.to_string()
            },
        };

        //统一的错误返回格式
        let body_param = json!(
            {
             "code": e_code,
             "msg": e_msg
            }
        );

        tracing::info!("返回数据={}",body_param);

        //特殊处理: 未授权
        if e_code == 401 {
           return  (StatusCode::UNAUTHORIZED, Json(body_param)).into_response()
        }
        
        (StatusCode::OK, Json(body_param)).into_response()
       
    }
}


// 使得 字符串可以转化成 CustomError
impl From<String> for CustomError {
    fn from(s: String) -> Self {
        CustomError::TipError(s)
    }
}

// 使得 切片可以转化成 CustomError
impl From<&str> for CustomError {
    fn from(s: &str) -> Self {
        CustomError::TipError(s.to_string())
    }
}